Skip to main content

MQTT Device

Configuring MQTT clients

MQTT clients authenticate devices by connecting to the MQTT bridge. To configure an MQTT client to authenticate a device:

  1. Set the MQTT client ID to the full device path:
    Client Identifier
    subscriptions/SUBSCRIPTION_ID/registries/REGISTRY_ID/devices/DEVICE_ID
  2. Associate the MQTT client with MQTT server certificates.
  3. Set the MQTT host name to hostprefix.mqtt.korewireless.com or a long-term support domain (if you used the minimal root CA set).
  4. Specify a username. The MQTT bridge ignores the username field, but some MQTT client libraries will not send the password field unless the username field is specified. For best results, supply an arbitrary username like unused or ignored.
  5. Set the password. The password field must contain the JWT.

The following sample shows how to configure the MQTT client to authenticate a device:

The steps for configuring the client ID and authenticating a device
package main

import (
"crypto/tls"
"crypto/x509"
"flag"
"fmt"
"io/ioutil"
"log"
"time"

MQTT "github.com/eclipse/paho.mqtt.golang"
jwt "github.com/golang-jwt/jwt"
)

var (
deviceID = flag.String("device", "", "Omnicore Device ID")
bridge = struct {
host *string
port *string
}{
flag.String("mqtt_host", "hostprefix.mqtt.korewireless.com", "MQTT Bridge Host"),
flag.String("mqtt_port", "8883", "MQTT Bridge Port"),
}
subscriptionID = flag.String("subscription", "", "Omnicore Subscription ID")
registryID = flag.String("registry", "", "Omnicore Registry ID (short form)")
certsCA = flag.String("ca_certs", "", "Download https://pki.cloud.korewireless.com/roots.pem")
privateKey = flag.String("private_key", "", "Path to private key file")
)

func main() {
log.Println("[main] Entered")

log.Println("[main] Flags")
flag.Parse()

log.Println("[main] Loading Omnicore's roots")
certpool := x509.NewCertPool()
pemCerts, err := ioutil.ReadFile(*certsCA)
if err == nil {
certpool.AppendCertsFromPEM(pemCerts)
}

log.Println("[main] Creating TLS Config")

config := &tls.Config{
RootCAs: certpool,
ClientAuth: tls.NoClientCert,
ClientCAs: nil,
InsecureSkipVerify: true,
Certificates: []tls.Certificate{},
MinVersion: tls.VersionTLS12,
}

clientID := fmt.Sprintf("subscriptions/%v/registries/%v/devices/%v",
*subscriptionID,
*registryID,
*deviceID,
)

log.Println("[main] Creating MQTT Client Options")
opts := MQTT.NewClientOptions()

broker := fmt.Sprintf("ssl://%v:%v", *bridge.host, *bridge.port)
log.Printf("[main] Broker '%v'", broker)

opts.AddBroker(broker)
opts.SetClientID(clientID).SetTLSConfig(config)

opts.SetUsername("unused")

token := jwt.New(jwt.SigningMethodRS256)
token.Claims = jwt.StandardClaims{
IssuedAt: time.Now().Unix(),
ExpiresAt: time.Now().Add(24 * time.Hour).Unix(),
}

log.Println("[main] Load Private Key")
keyBytes, err := ioutil.ReadFile(*privateKey)
if err != nil {
log.Fatal(err)
}

log.Println("[main] Parse Private Key")
key, err := jwt.ParseRSAPrivateKeyFromPEM(keyBytes)
if err != nil {
log.Fatal(err)
}

log.Println("[main] Sign String")
tokenString, err := token.SignedString(key)
if err != nil {
log.Fatal(err)
}

opts.SetPassword(tokenString)

// Incoming
opts.SetDefaultPublishHandler(func(client MQTT.Client, msg MQTT.Message) {
fmt.Printf("[handler] Topic: %v\n", msg.Topic())
fmt.Printf("[handler] Payload: %v\n", msg.Payload())
})

log.Println("[main] MQTT Client Connecting")
client := MQTT.NewClient(opts)
if token := client.Connect(); token.Wait() && token.Error() != nil {
log.Fatal(token.Error())
}
}